﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TribesPSO
{
    /// <summary>
    /// A single threaded (partial) implementation of SearchSpace that moves the particles in a random order everytime Move() is called
    /// </summary>
    /// <remarks>
    /// SingleThreadedSearchSpace does not supply an implementation of GenerateParticleAtPosition(EuclidianVector position).
    /// For a concrete implementation of SingleThreadedSearchSpace, see SingleThreadedGaussianSearchSpace and 
    /// SingleThreadedHypersphereSearchSpace
    /// </remarks>
    public abstract class SingleThreadedSearchSpace<TParticle> : SearchSpace<TParticle> where TParticle : Particle
    {
        /// <summary>
        /// Initializes a SingleThreadedSearchSpace object to optimize the specified objective function using the default
        /// TribesPSO.HyperspaceRandom random number generator
        /// </summary>
        /// <param name="objectiveFunction">The IObjectiveFunction to optimize</param>
        protected SingleThreadedSearchSpace(IObjectiveFunction objectiveFunction)
            : base(objectiveFunction, new HyperspaceRandom()) { }

        /// <summary>
        /// Initializes a SingleThreadedSearchSpace object to optimize the specified objective function
        /// </summary>
        /// <param name="objectiveFunction">The IObjectiveFunction to optimize</param>
        /// <param name="randomNumberGenerator">An IHyperspaceRandom that will be used to move the particles</param>
        protected SingleThreadedSearchSpace(IObjectiveFunction objectiveFunction, IHyperspaceRandom randomNumberGenerator)
            : base(objectiveFunction, randomNumberGenerator) { }

        /// <summary>
        /// Moves all of the particles in the swarm. Particles are moved serially within a tribe.
        /// The tribes are moved in a random order
        /// </summary>
        protected override void Move()
        {
            foreach (var tribe in this.Tribes.InRandomOrder(this.RandomNumberGenerator))
            {
                foreach (var particle in tribe.TribeMembers)
                {
                    particle.Move();
                }
            }
        }
    }
}
